package com.zhongwang.mms.module.buy.service;

import com.zhongwang.mms.gen.entity.SysUser;
import com.zhongwang.mms.gen.entity.User;
import com.zhongwang.mms.gen.mapper.SysUserMapper;
import com.zhongwang.mms.module.basic.dao.DictCommonDao;
import com.zhongwang.mms.module.basic.dao.VerifyMapper;
import com.zhongwang.mms.module.basic.dao.VerifyProcessMapper;
import com.zhongwang.mms.module.basic.model.DictCommon;
import com.zhongwang.mms.module.basic.model.Verify;
import com.zhongwang.mms.module.basic.model.VerifyProcess;
import com.zhongwang.mms.module.buy.dao.BPreOrderPlanChangeDao;
import com.zhongwang.mms.module.buy.dao.BPreOrderPlanDao;
import com.zhongwang.mms.module.buy.dao.GenerateCodeDao;
import com.zhongwang.mms.module.buy.model.*;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.module.system.user.UserDao;
import com.zhongwang.mms.util.FileUtils;
import com.zhongwang.mms.util.ShiroUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.zhongwang.mms.constant.Constant.*;
import static com.zhongwang.mms.util.GenStringUtils.formatWithMicros;

/**
 * 预购采购逻辑业务层
 */
@SuppressWarnings("ALL")
@Service
@Log4j2
public class BuyPreOrderPlanService {
    @Autowired
    private BPreOrderPlanDao bPreOrderPlanDao;
    @Autowired
    private BPreOrderPlanChangeDao bPreOrderPlanChangeDao;
    @Autowired
    private GenerateCodeDao generateCodeDao;
    @Autowired
    private LogService logService;
    @Autowired
    private DictCommonDao dictCommonDao;
    @Autowired
    private VerifyMapper verifyMapper;
    @Autowired
    private VerifyProcessMapper verifyProcessMapper;
    @Autowired
    private UserDao userDao;
    /**
     * 上传文件路径
     */
    @Value("${user.upload.path}")
    private String uploadPath;
    /**
     * 向generate_code表获取一个新的预购code码
     * 实现原理。首先在b_pre_order_plan表中和generate_code表中寻找今天最后一个码，
     * 然后根据流水+1的方式生成新的码后，插入新码到generate_code中，然后返回给前端页面
     * @return
     */
    public String getNewCode() {
        String codePrefix = "YG_"+new SimpleDateFormat("yyyyMMdd").format(new Date());
        String lastCode = generateCodeDao.getBPreOrderPlanLastCode(codePrefix);
        int orderNo = 0;
        GenerateCode result = new GenerateCode();
        if(lastCode == null ||lastCode.isEmpty()){
            orderNo = 1;
            lastCode = codePrefix +String.format("%08d", orderNo);
            GenerateCode generateCode = new GenerateCode();
            generateCode.setType("预购编码");
            generateCode.setCode(lastCode);
            generateCode.setUserId(ShiroUtils.getUserId());
            generateCodeDao.insert(generateCode);
        }else{
            Integer sn = new Integer(lastCode.replace(codePrefix,""))+1;
            lastCode = codePrefix +String.format("%08d", sn);
            GenerateCode generateCode = new GenerateCode();
            generateCode.setType("预购编码");
            generateCode.setCode(lastCode);
            generateCode.setUserId(ShiroUtils.getUserId());
            generateCodeDao.insert(generateCode);
        }
        return lastCode;
    }

    /**
     * 向generate_code表获取一个新的预购流水跟踪号
     * 实现原理。首先在b_pre_order_plan表中和generate_code表中寻找最后一个码，
     * 然后根据流水+1的方式生成新的码后，插入新码到generate_code中，然后返回给前端页面
     * @return
     */
    public String genTrackNumber() {
        String codePrefix = "YG_";
        String lastTrackNumber = generateCodeDao.getBPreOrderPlanLastTrackNumber(codePrefix);
        int orderNo = 0;
        GenerateCode result = new GenerateCode();
        if(lastTrackNumber == null ||lastTrackNumber.isEmpty()){
            orderNo = 1;
            lastTrackNumber = codePrefix +String.format("%08d", orderNo);
            GenerateCode generateCode = new GenerateCode();
            generateCode.setType("物料跟踪号");
            generateCode.setCode(lastTrackNumber);
            generateCode.setUserId(ShiroUtils.getUserId());
            generateCodeDao.insert(generateCode);
        }else{
            Integer sn = new Integer(lastTrackNumber.replace(codePrefix,""))+1;
            lastTrackNumber = codePrefix +String.format("%08d", sn);
            GenerateCode generateCode = new GenerateCode();
            generateCode.setType("物料跟踪号");
            generateCode.setCode(lastTrackNumber);
            generateCode.setUserId(ShiroUtils.getUserId());
            generateCodeDao.insert(generateCode);
        }
        return lastTrackNumber;
    }

    /**
     * 查询项目号
     *
     * @param code 项目号
     * @return boolean
     */
    public boolean getProjectByCode(String code) {
        return generateCodeDao.getProjectByCode(code) != null;
    }

    /**
     * 保存导入的Excel的预购数据
     * @param bPreOrderPlanList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer saveImportExcelData(List<BPreOrderPlan> bPreOrderPlanList) {
        Integer res = 0;
        Date currentTime = new Date();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        //调用生成跟踪流水码8位,按照顺序生成，插入生成码的表
        for (BPreOrderPlan bPreOrderPlan : bPreOrderPlanList) {
            bPreOrderPlan.setTrackNumber(genTrackNumber());
            bPreOrderPlan.setCreateTime(currentTime);
            bPreOrderPlan.setApplicantId(user.getId());
            bPreOrderPlan.setChangeFlag(FORM_UNCHANGED);
            bPreOrderPlan.setPurchStatus(PURCH_STATUS_NOT);
            bPreOrderPlan.setReceiptStatus(RECEIPT_STATUS_NOT_RECEIVED);
            //未提交
            bPreOrderPlan.setStatus(FORM_STATUS_NOT_SUBMITTED);
        }
        //插入数据库
        res = bPreOrderPlanDao.insertList(bPreOrderPlanList);
        //插入数据库后删除生成码表的数据
        GenerateCode removeCode = new GenerateCode();
        removeCode.setUserId(ShiroUtils.getUserId());
        removeCode.setCode(bPreOrderPlanList.get(0).getCode());
        removeCode.setType("预购编码");
        res = generateCodeDao.deleteCodeByCodeAndTypeAndUserId(removeCode);
        //删除生成的物料跟踪号
        for (BPreOrderPlan bPreOrderPlan : bPreOrderPlanList) {
            GenerateCode removeTrackNumber = new GenerateCode();
            removeTrackNumber.setUserId(ShiroUtils.getUserId());
            removeTrackNumber.setCode(bPreOrderPlan.getTrackNumber());
            removeTrackNumber.setType("物料跟踪号");
            res = generateCodeDao.deleteCodeByCodeAndTypeAndUserId(removeTrackNumber);
        }
        return res;
    }

    /**
     * 查询预购计划列表
     * @param where
     * @return
     */
    public List<BPreOrderPlan> findBPreOrderPlanByQuery(BPreOrderPlan where) {
        return bPreOrderPlanDao.selectList(where);
    }

    /**
     * 根据预购编号code查询预购计划列表
     * @param code 预购编号
     * @return 预购计划列表
     */
    public List<BPreOrderPlan> findBPreOrderPlanByCode(String code) {
        return bPreOrderPlanDao.selectListByCode(code);
    }

    /**
     * 根据主键获取对应的预购计划数据
     * @param id
     * @return 对应的预购计划数据
     */
    public BPreOrderPlan getBPreOrderPlanByPrimaryKey(Integer id) {
        return bPreOrderPlanDao.selectByPrimaryKey(id);
    }

    /**
     * 插入数据到数据库
     * @param data
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer importExcelForUpdate(PreOrderPlanImportModel data) {
        Integer res = 0;
        //拆解模型，拼装成可以存储进数据库的模型
        List<BPreOrderPlan> bPreOrderPlanList = new ArrayList();
        Date currentTime = new Date();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        String idStr = "";
        for (int i = 0; i < data.getRows().size(); i++) {
            PreOrderPlanImportDataModel popidm = data.getRows().get(i);
            BPreOrderPlan bPreOrderPlan = new BPreOrderPlan();
            bPreOrderPlan.setId(popidm.getId());
            bPreOrderPlan.setName(data.getName());
            bPreOrderPlan.setCode(data.getCode());
            bPreOrderPlan.setMaterialDesc(popidm.getMaterialDesc());
            bPreOrderPlan.setMaterialCode(popidm.getMaterialCode());
            bPreOrderPlan.setProCode(popidm.getProCode());
            bPreOrderPlan.setProName(popidm.getProName());
            bPreOrderPlan.setPurchaser(popidm.getPurchaser());
            bPreOrderPlan.setNum(new BigDecimal(popidm.getNum()));
            bPreOrderPlan.setUnit(popidm.getUnit());
            bPreOrderPlan.setPreOrderRemark(popidm.getPreOrderRemark());
            bPreOrderPlan.setModel(popidm.getModel());
            bPreOrderPlan.setBrand(popidm.getBrand());
            bPreOrderPlan.setCreateTime(currentTime);
            bPreOrderPlan.setApplicantId(user.getId());
            //未提交
            bPreOrderPlan.setStatus(FORM_STATUS_NOT_SUBMITTED);
            //分析上传文件进行上传文件，将上传完毕的文件的相对路径更新到存储到数据库对应的字段
            if (popidm.getUploadFile() != null) {
                String path = uploadPath + "/preOrderPlan/";
                String fileNameNotHaveFileExtension = FileUtils.getFileNameWithoutExtension(popidm.getUploadFile().getOriginalFilename());
                String fileExtension = FileUtils.getFileExtension(popidm.getUploadFile().getOriginalFilename());
                String newFileName = fileNameNotHaveFileExtension + formatWithMicros(new Date()) +"."+fileExtension;
                String fileName = FileUtils.uploadGenDiyFileName(popidm.getUploadFile(), path, newFileName);
                String url = "/files/preOrderPlan/" + fileName;
                bPreOrderPlan.setAttachment(url);
                bPreOrderPlan.setAttachmentName(fileNameNotHaveFileExtension + "." + fileExtension);
                if(bPreOrderPlan.getId() != null && bPreOrderPlan.getId() != 0) {
                    BPreOrderPlan dbBPreOrderPlan = bPreOrderPlanDao.selectByPrimaryKey(bPreOrderPlan.getId());
                    if(dbBPreOrderPlan != null){
                        String attachmentUrl = dbBPreOrderPlan.getAttachment().replace("/files/", "/");
                        String localPath = uploadPath + attachmentUrl.substring(attachmentUrl.indexOf("/"));
                        File file = new File(localPath);
                        if(file.exists()){
                            file.delete();
                        }
                    }
                }
            }else{
                if(bPreOrderPlan.getId() != null && bPreOrderPlan.getId() != 0) {
                    BPreOrderPlan dbBPreOrderPlan = bPreOrderPlanDao.selectByPrimaryKey(bPreOrderPlan.getId());
                    if(dbBPreOrderPlan != null){
                        bPreOrderPlan.setAttachment(dbBPreOrderPlan.getAttachment());
                        bPreOrderPlan.setAttachmentName(dbBPreOrderPlan.getAttachmentName());
                    }
                }
            }
            if(bPreOrderPlan.getId() != null && bPreOrderPlan.getId() != 0){
                idStr += bPreOrderPlan.getId()+",";
                bPreOrderPlan.setRejectReason("");//删除驳回原因
                //更新数据
                res += bPreOrderPlanDao.updatePreOrder(bPreOrderPlan);
            }else{
                bPreOrderPlan.setTrackNumber(genTrackNumber());
                bPreOrderPlan.setChangeFlag(FORM_UNCHANGED);
                bPreOrderPlan.setPurchStatus(PURCH_STATUS_NOT);
                bPreOrderPlan.setReceiptStatus(RECEIPT_STATUS_NOT_RECEIVED);
                bPreOrderPlanList.add(bPreOrderPlan);
            }
        }
        if(!idStr.equals("")) {
            idStr = idStr.substring(0, idStr.length() - 1);
        }
        //删除不需要的数据和对应附件
        if(!idStr.equals("")){
            List<BPreOrderPlan> removeProOrderList = bPreOrderPlanDao.selectLitByCodeAndHaveIdStr(data.getCode(),idStr);
            for(BPreOrderPlan bPreOrderPlan:removeProOrderList){
                if(bPreOrderPlan != null && bPreOrderPlan.getAttachment()!=null && !bPreOrderPlan.getAttachment().equals("")){
                    String attachmentUrl = bPreOrderPlan.getAttachment().replace("/files/", "/");
                    String localPath = uploadPath + attachmentUrl.substring(attachmentUrl.indexOf("/"));
                    File file = new File(localPath);
                    if(file.exists()){
                        file.delete();
                    }
                }
            }
            res += bPreOrderPlanDao.deleteByCodeAndNotHaveIdStr(data.getCode(),idStr);
        }
        //插入新增的数据
        if(bPreOrderPlanList.size()>0) {
            res += bPreOrderPlanDao.insertList(bPreOrderPlanList);
        }
        if(bPreOrderPlanList.size()>0){
            //插入数据库后删除生成码表的数据
            GenerateCode removeCode = new GenerateCode();
            removeCode.setUserId(ShiroUtils.getUserId());
            removeCode.setCode(bPreOrderPlanList.get(0).getCode());
            removeCode.setType("预购编码");
            res += generateCodeDao.deleteCodeByCodeAndTypeAndUserId(removeCode);
            //删除生成的物料跟踪号
            for (BPreOrderPlan bPreOrderPlan : bPreOrderPlanList) {
                GenerateCode removeTrackNumber = new GenerateCode();
                removeTrackNumber.setUserId(ShiroUtils.getUserId());
                removeTrackNumber.setCode(bPreOrderPlan.getTrackNumber());
                removeTrackNumber.setType("物料跟踪号");
                res += generateCodeDao.deleteCodeByCodeAndTypeAndUserId(removeTrackNumber);
            }
        }

        return res;
    }
    /**
     * 根虎预购编号删除预购计划
     * @param code
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteByCodes(List<String> codes) {
        Integer res = 0;
        for (int i = 0; i < codes.size(); i++) {
            String code = codes.get(i);
            List<BPreOrderPlan> removeProOrderList = bPreOrderPlanDao.selectListByCode(code);
            for(BPreOrderPlan bPreOrderPlan:removeProOrderList){
                if(bPreOrderPlan != null && bPreOrderPlan.getAttachment()!=null && !bPreOrderPlan.getAttachment().equals("")){
                    String attachmentUrl = bPreOrderPlan.getAttachment().replace("/files/", "/");
                    String localPath = uploadPath + attachmentUrl.substring(attachmentUrl.indexOf("/"));
                    File file = new File(localPath);
                    if(file.exists()){
                        file.delete();
                    }
                }
            }
            logService.saveLog("采购管理-预购计划编辑","删除预购编号为：【"+code+"】的预购计划！");
            res += bPreOrderPlanDao.deleteByCodeAndNotHaveIdStr(code,"");
            res += verifyProcessMapper.delBySheetCode(code);
        }
        return res;
    }
    /**
     * 根据预购编号提交预购计划
     * @param code
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer submitByCodes(List<String> codes) {
        Integer res = 0;
        for (String code : codes) {
            List<BPreOrderPlan> submitProOrderList = bPreOrderPlanDao.selectListByCode(code);
            for (BPreOrderPlan bPreOrderPlan : submitProOrderList) {
                if(bPreOrderPlan.getStatus().intValue() == FORM_STATUS_NOT_SUBMITTED || bPreOrderPlan.getStatus().intValue() == FORM_STATUS_REJECTED){
                    //设置成已提交
                    bPreOrderPlan.setStatus(FORM_STATUS_SUBMITTED);
                    res += bPreOrderPlanDao.updatePreOrderStatus(bPreOrderPlan);
                    bPreOrderPlan.setAssignPurchaserId(null);
                    bPreOrderPlan.setRejectReason(null);
                    res += bPreOrderPlanDao.updateBPreOrderPlanAssignPurchaserIdAndRejectReason(bPreOrderPlan);
                }
            }
            // 查询审核配置
            Verify verify = new Verify();
            DictCommon preOrderTypeWhere = new DictCommon();
            preOrderTypeWhere.setName("预购计划");
            preOrderTypeWhere.setGroupName("单据类型");
            verify.setReportType(dictCommonDao.selectByNameAndGroupName(preOrderTypeWhere).getValue());
            List<Verify> verifyList = verifyMapper.findByCondition(verify);
            // 生成审核记录
            for (int i = 0; i < verifyList.size(); i++) {
                VerifyProcess vp = new VerifyProcess();
                vp.setSheetCode(code);
                vp.setOrderNo(verifyList.get(i).getOrderNo());
                vp.setComp(verifyList.get(i).getComp());
                if (i == 0) {
                    vp.setCur(1);
                    vp.setStart(1);
                } else {
                    vp.setCur(0);
                    vp.setStart(0);
                }
                vp.setStatus(1);
                vp.setVerifier(verifyMapper.findVerifier(ShiroUtils.getUserId(), verifyList.get(i).getPost()));
                verifyProcessMapper.insert(vp);
            }
            logService.saveLog("采购管理-预购计划编辑","提交预购编号为：【"+code+"】的预购计划！");
        }
        return res;
    }

    /**
     * 根据部门名称获取所属部门的用户列表
     * @param name
     * @return
     */
    public List<SysUser> findSysUserListByDeptName(String name) {
        return userDao.selectByDeptName(name);
    }

    /**
     * 指派
     * @param code 被指派预购编号
     * @param assignPurchaserId 被指派的业务员ID
     * @return 指派结果
     */
    public Integer assign(String code, Integer assignPurchaserId) {
        Integer res = 0;
        List<BPreOrderPlan> submitProOrderList = bPreOrderPlanDao.selectListByCode(code);
        for (BPreOrderPlan bPreOrderPlan : submitProOrderList) {
            if(bPreOrderPlan.getStatus().intValue() == FORM_ALL_APPROVED){
                bPreOrderPlan.setAssignPurchaserId(assignPurchaserId);
                bPreOrderPlan.setStatus(FORM_ASSIGNED);
                res += bPreOrderPlanDao.updatePreOrderStatusAndAssignPurchaserId(bPreOrderPlan);
            }
        }
        if(res > 0){
            User user = userDao.findUserById(assignPurchaserId);
            logService.saveLog("采购管理-预购计划编辑","指派预购编号为：【"+code+"】的预购计划，给业务员【"+user.getName()+"】！");
        }
        return res;
    }

    /**
     * 驳回
     * @param codes 驳回的预购编码集合
     * @param rejectReason 驳回原因
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer reject(List<String> codes, String rejectReason) {
        Integer result = 0;
        for (String code : codes) {
            VerifyProcess vp = verifyProcessMapper.findCompVpBySheetCode(code);
            List<BPreOrderPlan> bPreOrderPlanList = bPreOrderPlanDao.selectListByCode(code);
            logService.saveLog("采购管理-预购计划编辑", "驳回未指派的采购计划，预购编号为：" + vp.getSheetCode());
            for (BPreOrderPlan bPreOrderPlan : bPreOrderPlanList) {
                if(rejectReason.equals("")){
                    bPreOrderPlan.setRejectReason("被驳回");
                }else{
                    bPreOrderPlan.setRejectReason(rejectReason);
                }
                bPreOrderPlan.setStatus(FORM_STATUS_REJECTED);
                result += bPreOrderPlanDao.updatePreOrder(bPreOrderPlan);
            }
            //直接驳回到提交前
            result += verifyProcessMapper.delBySheetCode(code);
        }
        return result;
    }
}
